namespace taurus.client {

    /**
     * SocketEngine
     */
    export class HttpClient implements IScoketLayer {
        private static _Method: string = "POST";
        private static readonly NULL_BYTES: Uint8Array = new Uint8Array(0);
        private static _Result: string = "$r";
        private static _Param: string = "$p";
        private static _Session: string = "$s";
        private static _Version: string = "$v";
        _url: string = "";
        _session_id: string = "";

        public constructor(url: string) {
            this._url = url;
        }

        connect(ip: string, game: string): boolean {
            return true;
        }

        disconnect(): boolean {
            return true;
        }

        //判断字符是否为空的方法
        private _isEmpty(obj: string): boolean {
            if (typeof obj == "undefined" || obj == null || obj == "") {
                return true;
            } else {
                return false;
            }
        }

        private __sendMsg(msg: Message) {
            var bytes = HttpClient.NULL_BYTES;
            var _data = TObject.newInstance();
            _data.putString(HttpClient._Session, this._session_id);
            _data.putInt(HttpClient._Version, NetManager.VERSION);
            if (msg.useText && msg.param == null) {
                if (this._isEmpty(msg.textParam)) {
                    msg.param = TObject.newInstance();
                } else {
                    try {
                        msg.param = TObject.newFromJson(msg.textParam);
                    } catch (e) {
                        msg.param = TObject.newInstance();
                    }
                }
            }
            _data.putTObject(HttpClient._Param, msg.param);
            var buff = _data.toBinary();
            try {
                buff.compress();
            } catch (e) {
                log.error(e);
            }
            bytes = buff.bytes;

            this.__requestAsync(msg, bytes);
        }

        private __response(code: number, msg: Message) {
            if (msg.callback != null) {
                var response = new MessageResponse();
                response.messageData = msg;
                response.returnCode = code;
                msg.callback(response);
            }
        }

        private __requestAsync(msg: Message, bytes: Uint8Array) {
            var self = this;
            var xhs = new XMLHttpRequest();
            xhs.timeout = NetManager.TIMEOUT_TIME * 1000;
            xhs.open(HttpClient._Method, this._url + msg.command, true);
            xhs.ontimeout = function (evt) {
                self.__response(102, msg);
            };
            xhs.onerror = function (evt) {
                self.__response(101, msg);
            };
            xhs.onload = function (evt) {
                var code = 500;
                if (xhs.readyState == 4 && xhs.status == 200) {
                    var _data = xhs.response;
                    if (_data) {
                        let bytes = new ByteArray(_data);
                        bytes.uncompress();
                        var tem = TObject.newFromBinaryData(bytes);
                        var result = tem.getInt(HttpClient._Result);

                        if (result == 0) {
                            var _param = tem.getTObject(HttpClient._Param);
                            msg.param = _param;
                            if (msg.useText) {
                                msg.textParam = _param.toJson();
                            }
                        }
                        code = result;
                    }
                }
                self.__response(code, msg);
            }
            xhs.responseType = "arraybuffer";
            xhs.send(bytes);
        }


        write(msg: Message) {
            this.__sendMsg(msg);
        }

        getProtocol(): ConnectionProtocol {
            return ConnectionProtocol.Web;
        }

        setOnConnect(onConnect: (code: SocketCode) => void, thisObject: any) {
        }

        setOnEvent(onEvent: (msg: Message) => void, thisObject: any) {
        }

        getAveragePingTime(): number {
            return 100;
        }

        getSession(): string {
            return this._session_id;
        }

        setSession(session: string) {
            this._session_id = session;
        }

    }
}